home *** CD-ROM | disk | FTP | other *** search
- #include <stdlib.h>
- #include <stdio.h>
- #include <time.h>
- #include <math.h>
- #include <string.h>
-
- #include "random.h"
- #include "world.h"
-
- #define _MAKE_CRATERS
- #define _USE_ROUGHNESS_MAP
- //#define _BIZARRE_ROUGHNESS_MAP
- //#define _BIZARRE_ALT_MAP
- //#define DEBUG
-
- //----------------------------------------------------------------------------
- // The maps. Note that, in this module, the color_map array is used during
- // the generation of the altitude map, so in that case, it is misnamed.
- //----------------------------------------------------------------------------
-
- map_t far alt_map;
- map_t far color_map;
-
- //----------------------------------------------------------------------------
- // An internal temporary map used in generating the other maps:
- //----------------------------------------------------------------------------
-
- static map_t temp_map;
-
- //----------------------------------------------------------------------------
- // Assertion code for this module:
- //----------------------------------------------------------------------------
-
- #ifdef DEBUG
-
- static void _Assert
- (
- const char * file,
- unsigned line,
- const char * assertion
- )
- {
- fflush (stdout);
- fprintf ( stderr, "\nAssertion failed (%s, line %u): %s\n",
- file, line, assertion );
- fflush (stderr);
- abort ();
- }
-
- #define ASSERT(f) if (f) {} else _Assert ( __FILE__, __LINE__, #f )
-
- #else
-
- #define ASSERT(f)
-
- #endif
-
- //----------------------------------------------------------------------------
- // FUNCTION rough_init
- //----------------------------------------------------------------------------
-
- #ifdef _USE_ROUGHNESS_MAP
-
- static void rough_init
- (
- void
- )
- {
- int x, y;
-
- for ( x = 0; x < map_size_x; x += 64 )
- {
- for ( y = 0; y < map_size_y; y += 64 )
- {
- color_map [x][y] = (unsigned char) (random ( 128 ) + 80);
- }
- }
- }
-
- #endif
-
- //----------------------------------------------------------------------------
- // FUNCTION map_init
- //----------------------------------------------------------------------------
-
- static void map_init
- (
- void
- )
- {
- int x, y;
-
- for ( x = 0; x < map_size_x; x += 64 )
- {
- for ( y = 0; y < map_size_y; y += 64 )
- {
- color_map [x][y] = (unsigned char) random ( 256 );
- }
- }
- }
-
- //----------------------------------------------------------------------------
- // FUNCTION flat_area
- //----------------------------------------------------------------------------
-
- static void flat_area(
- int map_x,
- int map_y,
- int size_x,
- int size_y,
- int height_offset/* = 0 */
- )
- {
- int height;
- int x, y;
-
- // First get the average height of the original rectangular region.
-
- height = 0;
-
- for ( x = 0; x < size_x; ++ x ){
- for ( y = 0; y < size_y; ++ y ){
- height +=
- (int) alt_map [(x+map_x) & clip_mask_x][(y+map_y) & clip_mask_y];
- }
- }
-
- height /= size_x * size_y;
-
- // Offset from the average height.
-
- height += height_offset;
- if ( height < min_alt ) height = min_alt;
- else if ( height > max_alt-1 ) height = max_alt - 1;
-
- // Put in the landing pad.
-
- for ( x = 0; x < size_x; ++ x ){
- for ( y = 0; y < size_y; ++ y ){
- alt_map [(x+map_x) & clip_mask_x][(y+map_y) & clip_mask_y] =
- (unsigned char) (height + random (2));
- }
- }
- }
-
- //----------------------------------------------------------------------------
- // FUNCTION quonset_hut
- //----------------------------------------------------------------------------
- // These quonset huts run parallel to the Y axis.
- //----------------------------------------------------------------------------
-
- static void quonset_hut
- (
- int map_x,
- int map_y,
- int size_y
- )
- {
- int average;
- int x, y;
- int r_squared;
- const radius = 4;
-
- // First get the average height of the original region.
-
- average = 0;
-
- for ( x = 0; x < radius * 2; ++ x ){
- for ( y = 0; y < size_y; ++ y ){
- average +=alt_map [(x+map_x) & clip_mask_x][(y+map_y) & clip_mask_y];
- }
- }
-
- average /= size_y * radius * 2;
-
- // Bury the quonset hut a bit.
-
- average -= scale_area / scale_height;
-
- // Build the hut.
-
- r_squared = radius * radius;
-
- for ( x = 0; x < radius * 2; ++ x ){
- int height =
- (int) sqrt ( (double) (r_squared - (x-radius)*(x-radius) + 1) );
- height *= (scale_area / scale_height);
- height += average;
- if ( height > max_alt ) height = max_alt;
-
- for ( y = 0; y < size_y; ++ y ){
- alt_map [(x+map_x) & clip_mask_x][(y+map_y) & clip_mask_y] =(unsigned char) height;
- }
- }
- }
-
- //----------------------------------------------------------------------------
- // FUNCTION generate_roughness_map
- //----------------------------------------------------------------------------
-
- #ifdef _USE_ROUGHNESS_MAP
-
- static void generate_roughness_map(void)
- {
- int counter = 0;
- int which = 0;
- int square_size,x1,y1;
- printf ( " Roughness map: 0 %%" );
-
- rough_init ();
-
- for ( square_size = 64; square_size > 1; square_size /= 2 ){
- for ( x1 = 0; x1 < map_size_x; x1 += square_size ) {
- for ( y1 = 0; y1 < map_size_y; y1 += square_size ) {
- // Get the four influential points.
-
- int x2 = (x1 + square_size) & clip_mask_x;
- int y2 = (y1 + square_size) & clip_mask_y;
-
- int i1, i2, i3, i4;
- int p1,p2,p3,p4;
- int random_center,random_range;
-
- if ( which == 0 )
- {
- i1 = color_map [x1][y1];
- i2 = color_map [x2][y1];
- i3 = color_map [x1][y2];
- i4 = color_map [x2][y2];
- }else{
- i1 = alt_map [x1][y1];
- i2 = alt_map [x2][y1];
- i3 = alt_map [x1][y2];
- i4 = alt_map [x2][y2];
- }
-
- // Obtain new points by averaging the influential points.
-
- p1 = ((i1 * 9) + (i2 * 3) + (i3 * 3) + (i4)) / 16;
- p2 = ((i1 * 3) + (i2 * 9) + (i3) + (i4 * 3)) / 16;
- p3 = ((i1 * 3) + (i2) + (i3 * 9) + (i4 * 3)) / 16;
- p4 = ((i1) + (i2 * 3) + (i3 * 3) + (i4 * 9)) / 16;
-
- // Add a random offset to each new point.
-
- random_center = square_size;
- random_range = random_center * 2;
-
- #ifdef _BIZARRE_ROUGHNESS_MAP
-
- p1 += random (random_center) + random_range - (max_alt - p1)/6;
- p2 += random (random_center) + random_range - (max_alt - p2)/6;
- p3 += random (random_center) + random_range - (max_alt - p3)/6;
- p4 += random (random_center) + random_range - (max_alt - p4)/6;
-
- #else
-
- p1 += random (random_range) - random_center;
- p2 += random (random_range) - random_center;
- p3 += random (random_range) - random_center;
- p4 += random (random_range) - random_center;
-
- #endif
-
- // Boundary check the altitudes. Under the normal condition,
- // altitudes that are out of range will be "reflected" back into
- // the allowable range. Under the bizarre condition, we do
- // something bizarre!
-
- #ifdef _BIZARRE_ROUGHNESS_MAP
-
- p1 = (p1 < min_alt) ? max_alt + p1 + 1 : p1;
- p2 = (p2 < min_alt) ? max_alt + p2 + 1 : p2;
- p3 = (p3 < min_alt) ? max_alt + p3 + 1 : p3;
- p4 = (p4 < min_alt) ? max_alt + p4 + 1 : p4;
-
- p1 = (p1 > max_alt) ? (p1 % (max_alt+1)) : p1;
- p2 = (p2 > max_alt) ? (p2 % (max_alt+1)) : p2;
- p3 = (p3 > max_alt) ? (p3 % (max_alt+1)) : p3;
- p4 = (p4 > max_alt) ? (p4 % (max_alt+1)) : p4;
-
- #else
-
- p1 = (p1 < min_alt) ? (min_alt - p1) + min_alt : p1;
- p2 = (p2 < min_alt) ? (min_alt - p2) + min_alt : p2;
- p3 = (p3 < min_alt) ? (min_alt - p3) + min_alt : p3;
- p4 = (p4 < min_alt) ? (min_alt - p4) + min_alt : p4;
-
- p1 = (p1 > max_alt) ? (max_alt - p1) + max_alt : p1;
- p2 = (p2 > max_alt) ? (max_alt - p2) + max_alt : p2;
- p3 = (p3 > max_alt) ? (max_alt - p3) + max_alt : p3;
- p4 = (p4 > max_alt) ? (max_alt - p4) + max_alt : p4;
-
- #endif
-
- // Write out the generated points.
-
- x2 = (x1 + square_size/2) & clip_mask_x;
- y2 = (y1 + square_size/2) & clip_mask_y;
-
- if ( which == 0 ){
- alt_map [x1][y1] = (unsigned char) p1;
- alt_map [x2][y1] = (unsigned char) p2;
- alt_map [x1][y2] = (unsigned char) p3;
- alt_map [x2][y2] = (unsigned char) p4;
- }else {
- color_map [x1][y1] = (unsigned char) p1;
- color_map [x2][y1] = (unsigned char) p2;
- color_map [x1][y2] = (unsigned char) p3;
- color_map [x2][y2] = (unsigned char) p4;
- }
-
- counter += 100;
- }
- {
- int percent_done = (int) ( counter / 87360 );
- printf ( "\b\b\b\b\b%3d %%", percent_done );
- }
- }
-
- which = (which == 0) ? 1 : 0;
- }
-
- if ( which == 0 ){
- memcpy ( temp_map, color_map, sizeof (temp_map) );
- }else{
- memcpy ( temp_map, alt_map, sizeof (temp_map) );
- }
-
- printf ( "\b\b\b\b\bdone \n" );
- }
-
- #endif
-
- //----------------------------------------------------------------------------
- // FUNCTION generate_alt_map
- //----------------------------------------------------------------------------
-
- static void generate_alt_map(void)
- {
- int which = 0;
- int counter = 0;
- int square_size,i,x,y,x1,y1;
-
- #ifdef _USE_ROUGHNESS_MAP
-
- generate_roughness_map ();
-
- #endif
-
- printf ( " Altitude map: 0 %%" );
- fflush ( stdout );
-
- map_init ();
-
-
- for ( square_size = 64; square_size > 1; square_size /= 2 ){
- #ifdef _MAKE_CRATERS
-
- if ( square_size == 8 || square_size == 4 ){
- for ( i = 0; i < map_size_x * 3; ++ i ){
- if ( which == 0 )
- color_map [random (map_size_x)][random (map_size_y)]
- = (unsigned char) random (32);
- else
- alt_map [random (map_size_x)][random (map_size_y)]
- = (unsigned char) random (32);
- }
- }
-
- #endif
-
- // Make pseudo-valley floors.
-
- if ( square_size == 2 ){
- for ( x = 0; x < map_size_x; ++ x ){
- for ( y = 0; y < map_size_y; ++ y ){
- const cutoff_point = (max_alt+1) / 4;
-
- if ( alt_map [x][y] < cutoff_point ){
- alt_map [x][y] = (unsigned char) (cutoff_point - alt_map [x][y]/2);
- }
- }
- }
- }
-
- for ( x1 = 0; x1 < map_size_x; x1 += square_size ) {
- for ( y1 = 0; y1 < map_size_y; y1 += square_size ){
- // Get the four influential points.
-
- int x2 = (x1 + square_size) & clip_mask_x;
- int y2 = (y1 + square_size) & clip_mask_y;
-
- int i1, i2, i3, i4;
- int p1,p2,p3,p4;
- int random_center,random_range;
-
- if ( which == 0 ){
- i1 = color_map [x1][y1];
- i2 = color_map [x2][y1];
- i3 = color_map [x1][y2];
- i4 = color_map [x2][y2];
- } else {
- i1 = alt_map [x1][y1];
- i2 = alt_map [x2][y1];
- i3 = alt_map [x1][y2];
- i4 = alt_map [x2][y2];
- }
-
- // Obtain new points by averaging the influential points.
-
- p1 = ((i1 * 9) + (i2 * 3) + (i3 * 3) + (i4)) / 16;
- p2 = ((i1 * 3) + (i2 * 9) + (i3) + (i4 * 3)) / 16;
- p3 = ((i1 * 3) + (i2) + (i3 * 9) + (i4 * 3)) / 16;
- p4 = ((i1) + (i2 * 3) + (i3 * 3) + (i4 * 9)) / 16;
-
- // Add a random offset to each new point.
-
- #ifdef _USE_ROUGHNESS_MAP
- random_center = square_size * temp_map [x1][y1] / 84;
- #else
- random_center = square_size * 2;
- #endif
-
- random_range = random_center * 2;
-
- #ifdef _BIZARRE_ALT_MAP
-
- p1 += ( random ( random_range ) - random_center + p1/4 );
- p2 += ( random ( random_range ) - random_center + p2/4 );
- p3 += ( random ( random_range ) - random_center + p3/4 );
- p4 += ( random ( random_range ) - random_center + p4/4 );
-
- #else
-
- p1 += ( random ( random_range ) - random_center );
- p2 += ( random ( random_range ) - random_center );
- p3 += ( random ( random_range ) - random_center );
- p4 += ( random ( random_range ) - random_center );
-
- #endif
-
- // Boundary checking
-
- p1 = (p1 < min_alt) ? (min_alt - p1) + min_alt : p1;
- p2 = (p2 < min_alt) ? (min_alt - p2) + min_alt : p2;
- p3 = (p3 < min_alt) ? (min_alt - p3) + min_alt : p3;
- p4 = (p4 < min_alt) ? (min_alt - p4) + min_alt : p4;
-
- #ifdef _BIZARRE_ALT_MAP
-
- p1 = (p1 > max_alt) ? (p1 - (max_alt+1)) : p1;
- p2 = (p2 > max_alt) ? (p2 - (max_alt+1)) : p2;
- p3 = (p3 > max_alt) ? (p3 - (max_alt+1)) : p3;
- p4 = (p4 > max_alt) ? (p4 - (max_alt+1)) : p4;
-
- #else
-
- p1 = (p1 > max_alt) ? (max_alt - p1) + max_alt : p1;
- p2 = (p2 > max_alt) ? (max_alt - p2) + max_alt : p2;
- p3 = (p3 > max_alt) ? (max_alt - p3) + max_alt : p3;
- p4 = (p4 > max_alt) ? (max_alt - p4) + max_alt : p4;
-
- #endif
-
- // Write out the generated points.
-
- x2 = (x1 + square_size/2) & clip_mask_x;
- y2 = (y1 + square_size/2) & clip_mask_y;
-
- if ( which == 0 ){
- alt_map [x1][y1] = (unsigned char) p1;
- alt_map [x2][y1] = (unsigned char) p2;
- alt_map [x1][y2] = (unsigned char) p3;
- alt_map [x2][y2] = (unsigned char) p4;
- } else{
- color_map [x1][y1] = (unsigned char) p1;
- color_map [x2][y1] = (unsigned char) p2;
- color_map [x1][y2] = (unsigned char) p3;
- color_map [x2][y2] = (unsigned char) p4;
- }
-
- counter += 100;
- }
- {
- int percent_done = (int) ( counter / 87360 );
- printf ( "\b\b\b\b\b%3d %%", percent_done );
- }
- }
-
- which = (which == 0) ? 1 : 0;
- }
-
- if ( which == 0 ){
- memcpy ( alt_map, color_map, map_size_x * map_size_y );
- }
-
- // Create some man-made features in the landscape.
-
- flat_area ( 0, 0, 20, 20,0 );
- quonset_hut ( 0, 20, 24 );
-
- // We're done!
-
- printf ( "\b\b\b\b\bdone \n" );
- fflush ( stdout );
- }
-
- //----------------------------------------------------------------------------
- // FUNCTION calc_color_map
- //----------------------------------------------------------------------------
-
- static void calc_color_map( void)
- {
- int x, y;
- int color;
- int percent_done;
-
- int * shadow;
-
- shadow = (int *) calloc ( map_size_y, sizeof (int) );
- ASSERT ( shadow != NULL );
-
- printf ( " Shading map: 0 %%" );
- fflush ( stdout );
-
- for ( x = 0; x < map_size_x; ++ x ) {
- for ( y = 0; y < map_size_y; ++ y ) {
- int slope = alt_map [x][y] - alt_map [(x-1)&clip_mask_x][y];
-
- slope *= 2;
- slope += 40;
-
- if ( slope < 0 ) slope = 0;
- if ( slope > 63 ) slope = 63;
-
- color = slope + 1;
-
- color_map [x][y] = (unsigned char) color;
- }
-
- percent_done = x * 24 / map_size_x;
-
- printf ( "\b\b\b\b\b%3d %%", percent_done );
- }
-
- // Cast shadows.
-
- for ( y = 0; y < map_size_y; ++ y ) {
- shadow [y] = (int) alt_map [0][y];
- }
-
- for ( x = 1; x < map_size_x; ++ x ) {
- for ( y = 0; y < map_size_y; ++ y ) {
- int height;
- shadow [y] -= 3;
- if ( shadow [y] < 0 ) shadow [y] = 0;
-
- height = (int) alt_map [x][y];
-
- if ( height >= shadow [y] ) {
- shadow [y] = height;
-
- temp_map [x][y] = 0;
- } else {
- temp_map [x][y] = 1;
- }
- }
-
- percent_done = x * 23 / map_size_x + 24;
-
- printf ( "\b\b\b\b\b%3d %%", percent_done );
- }
-
- for ( x = 0; x < 128; ++ x ) {
- for ( y = 0; y < map_size_y; ++ y ) {
- int height;
- shadow [y] -= 3;
- if ( shadow [y] < 0 ) shadow [y] = 0;
-
- height = (int) alt_map [x][y];
-
- if ( height >= shadow [y] ){
- shadow [y] = height;
-
- temp_map [x][y] = 0;
- } else {
- temp_map [x][y] = 1;
- }
- }
-
- percent_done = x * 6 / map_size_x + 47;
-
- printf ( "\b\b\b\b\b%3d %%", percent_done );
- }
-
- for ( x = 0; x < map_size_x; ++ x ){
- for ( y = 0; y < map_size_y; ++ y ){
- if ( temp_map [x][y] ){
- int color = (int) color_map [x][y];
- color -= 18;
- if ( color < 1 )
- color = 1;
- color_map [x][y] = (unsigned char) color;
- }
- }
-
- percent_done = x * 23 / map_size_x + 53;
-
- printf ( "\b\b\b\b\b%3d %%", percent_done );
- }
-
- // Average the map colors to make the map appear smoother.
-
- for ( x = 0; x < map_size_x; ++ x ){
- for ( y = 0; y < map_size_y; ++ y ){
- color = 6 * color_map [x][y];
- color += 4 * color_map [(x+1) & clip_mask_x][y];
- color += 4 * color_map [x][(y+1) & clip_mask_y];
- color += 2 * color_map [(x+1) & clip_mask_x][(y+1) & clip_mask_y];
-
- color /= 16;
-
- color_map [x][y] = (unsigned char) color;
- }
-
- percent_done = x * 24 / map_size_x + 76;
-
- printf ( "\b\b\b\b\b%3d %%", percent_done );
- }
-
- free (shadow);
-
- printf ( "\b\b\b\b\bdone \n" );
- fflush ( stdout );
- }
-
- //----------------------------------------------------------------------------
- // FUNCTION WORLD_generate
- //----------------------------------------------------------------------------
-
- void WORLD_generate (void )
- {
- printf ( "\nGenerating the moonscape...\n\n" );
-
- randomize ();
- generate_alt_map ();
- calc_color_map ();
- }
-